package com.tools.web.interceptor.auth;

import com.tools.common.container.MapEnum;
import com.tools.common.container.OwnPairs;
import com.tools.common.object.Note;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 同一个用户的多种设备类型的登录记录的用户认证包装类
 * */
@Note("同一个用户的多种设备类型的登录记录的用户认证包装类")
public final class MultiAuthUser extends GenericAuthUser {

    @Note("每个设备对应的登录记录以及它们的过期时间（毫秒）")
    private ConcurrentHashMap<String, LinkedHashMap<String, Long>> deviceAndLoginRecord;

    @Note("设备类型 ID")
    private transient String deviceTypeId;

    @Note("用户登录记录的标识")
    private transient String uuid;

    @Note("用户类型标识。（比如平台用户、小程序用户等等）")
    private transient String userType;

    /* **************************************************************************************
     *
     *          构造器
     *
     * **************************************************************************************
     * */

    private MultiAuthUser() {
        super();
    }

    public MultiAuthUser(Object userId, Object user,
                         Map roleKeyMap, Map permissionIds,
                         Iterable<?> routers) {
        super(userId, user, roleKeyMap, permissionIds, routers);
    }

    /* **************************************************************************************
     *
     *          Getter 等方法
     *
     * **************************************************************************************
     * */

    ConcurrentHashMap<String, LinkedHashMap<String, Long>> getDeviceAndLoginRecord() {
        if(deviceAndLoginRecord == null) {
            this.deviceAndLoginRecord = new ConcurrentHashMap<>();
        }
        return deviceAndLoginRecord;
    }

    @Override
    public String getUuid() {
        return uuid;
    }

    @Override
    public void setUuid(String uuid) {
        if(uuid == null || uuid.isEmpty()) {
            throw new NullPointerException("“用户登录记录的标识” 为空");
        }
        this.uuid = uuid;
    }

    @Override
    public String getDeviceTypeId() {
        return deviceTypeId;
    }

    @Override
    public void setDeviceTypeId(String deviceTypeId) {
        this.deviceTypeId = LoginDeviceTypeEnum.getEnum(deviceTypeId).getId();
    }

    @Override
    public String getUserType() {
        return (userType == null) ? "" : userType;
    }

    @Override
    public void setUserType(String userType) {
        this.userType = (userType == null) ? "" : userType;
    }

    @Override
    protected String protected_toStringPropertyString() {
        return ", deviceTypeId=" + deviceTypeId +
                ", uuid=" + uuid +
                ", deviceAndLoginRecord=" + deviceAndLoginRecord +
                ", userType=" + this.getUserType();
    }

    @Override
    public String toString() {
        return "MultiAuthUser{" +
                super.toString() +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        if (!super.equals(o)) return false;
        MultiAuthUser that = (MultiAuthUser) o;
        return Objects.equals(deviceAndLoginRecord, that.deviceAndLoginRecord) && Objects.equals(deviceTypeId, that.deviceTypeId) && Objects.equals(uuid, that.uuid) && Objects.equals(userType, that.userType);
    }

    @Override
    public int hashCode() {
        return Objects.hash(super.hashCode(), deviceAndLoginRecord, deviceTypeId, uuid, userType);
    }

    /* **************************************************************************************
     *
     *          自定义方法与实现的方法
     *
     * **************************************************************************************
     * */

    @Note("拷贝当前 uuid 到新的认证对象 targetAuthUser")
    public void copyUuid(MultiAuthUser targetAuthUser) {
        targetAuthUser.uuid = this.uuid;
    }

    @Note("拷贝当前设备类型 ID 到新的认证对象 targetAuthUser")
    public void copyDeviceTypeId(MultiAuthUser targetAuthUser) {
        targetAuthUser.deviceTypeId = this.deviceTypeId;
    }

    public void copyUserType(MultiAuthUser targetAuthUser) {
        targetAuthUser.userType = this.getUserType();
    }

    @Note("拷贝当前 uuid 和设备类型 ID 到新的认证对象 targetAuthUser")
    public void copyAdditional(MultiAuthUser targetAuthUser) {
        targetAuthUser.uuid = this.uuid;
        targetAuthUser.deviceTypeId = this.deviceTypeId;
        targetAuthUser.userType = this.getUserType();
    }

    @Override
    public MultiAuthUser cloneAuthUser() {
        MultiAuthUser newAuthUser = new MultiAuthUser();
        super.copyBaseUserDataTo(newAuthUser);
        super.copyCustomDataMapTo(newAuthUser);
        return newAuthUser;
    }


    @Note("拷贝同一个用户的多个客户端的登录记录到新认证对象里")
    public void copyUuidAndExpirationMapTo(MultiAuthUser newAuthUser) {
        if(this.deviceAndLoginRecord == null || this.deviceAndLoginRecord.isEmpty()) {
            return;
        }
        int size = MapEnum.calcInitSize(this.deviceAndLoginRecord.size());
        ConcurrentHashMap<String, LinkedHashMap<String, Long>> res = new ConcurrentHashMap<>(size);
        for (Map.Entry<String, LinkedHashMap<String, Long>> e : this.deviceAndLoginRecord.entrySet()) {
            res.put(e.getKey(), new LinkedHashMap<>(e.getValue()));
        }
        newAuthUser.deviceAndLoginRecord = res;
    }


    /* **************************************************************************************
     *
     *          重写的链式方法
     *
     * **************************************************************************************
     * */

    @Override
    public MultiAuthUser uuid(String uuid) {
        this.setUuid(uuid);
        return this;
    }

    @Override
    public MultiAuthUser deviceTypeId(String deviceType) {
        this.setDeviceTypeId(deviceType);
        return this;
    }

    @Override
    public MultiAuthUser userType(String userType) {
        this.setUserType(userType);
        return this;
    }

    @Override
    public MultiAuthUser userId(Object userId) {
        super.setUserId(userId);
        return this;
    }

    @Override
    public MultiAuthUser user(Object user) {
        super.setUser(user);
        return this;
    }

    @Override
    public MultiAuthUser userTypeClass(String userTypeClassName) {
        super.setUserTypeClass(userTypeClassName);
        return this;
    }

    @Override
    public MultiAuthUser roleKeyMap(Map roleKeyMap) {
        super.setRoleKeyMap(roleKeyMap);
        return this;
    }

    @Override
    public MultiAuthUser permissionKeyMap(Map permissionKeyMap) {
        super.setPermissionKeyMap(permissionKeyMap);
        return this;
    }

    @Override
    public MultiAuthUser routerList(Iterable routerList) {
        super.setRouterList(routerList);
        return this;
    }

    /* **************************************************************************************
     *
     *          链式调用方法
     *
     * **************************************************************************************
     * */

    @Override
    public MultiAuthUser putData(String name, Object value) {
        super.putData(name, value);
        return this;
    }

    @Override
    public MultiAuthUser putAllData(Map customData) {
        super.putAllData(customData);
        return this;
    }

    @Override
    public MultiAuthUser putAllData(OwnPairs customData) {
        super.putAllData(customData);
        return this;
    }

    @Override
    public MultiAuthUser putAllData(String jsonObject) {
        super.putAllData(jsonObject);
        return this;
    }

    @Override
    public MultiAuthUser putAllData(Object javaBean) {
        super.putAllData(javaBean);
        return this;
    }

    @Override
    public MultiAuthUser removeData(String name) {
        super.removeData(name);
        return this;
    }

    @Override
    public MultiAuthUser removeAllData(String... names) {
        super.removeAllData(names);
        return this;
    }

    @Override
    public MultiAuthUser removeAllData(Iterable<String> names) {
        super.removeAllData(names);
        return this;
    }

    @Override
    public MultiAuthUser clearData() {
        super.clearData();
        return this;
    }
}
